package service.calculator.aristocrat;

import java.math.BigDecimal;

import models.Payment;
import models.Rate;
import service.BillingCalculator;
import util.Rounder;

public class AristocratBillingCalculatorImpl implements BillingCalculator {

	
	public BigDecimal calculatePayment(final Rate rate, final Payment payment) {
		BigDecimal paymentCalculation = null;
		final AristocratPaymentType paymentType = AristocratPaymentType
				.valueOf(payment.paymentType);
		final BigDecimal paymentHrs = BigDecimal.valueOf(payment.hours);

		// 15 per day
        final BigDecimal ecolaRate = BigDecimal.valueOf(1.875);

		final BigDecimal rateValue = rate.value;
		BigDecimal billingRate = null;
		switch (paymentType) {
		case BASIC:
			BigDecimal basicRate = computeBasicBillingRate(rateValue);
			billingRate = basicRate;
			break;
		case OT:
			// Plus 25%
			BigDecimal otRate = rateValue.add(rateValue.multiply(BigDecimal
					.valueOf(0.25)));
			billingRate = otRate;
			break;
		case LHOT:
			// (BasicRate x 2) + ((BasicRate x 2) x 30%)
			BigDecimal lhotRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1)));
            lhotRate = lhotRate.add(lhotRate.multiply(BigDecimal.valueOf(0.30)));
            billingRate = lhotRate;
			break;
		case SHOT:
		case RDOT:
			// (BasicRate x 1.3) + ((BasicRate x 1.3) x 30%)
            BigDecimal shotRate = rateValue.multiply(BigDecimal.valueOf(1.3));
            shotRate = shotRate.add(shotRate.multiply(BigDecimal.valueOf(0.30)));
            billingRate = shotRate;
			break;
		case SHRT:
			// Only 30% of the rate + ecola rate
			BigDecimal shrtRate = rateValue.add(ecolaRate).multiply(BigDecimal.valueOf(0.3));
			billingRate = shrtRate;
			break;
		case RDRT:
			// Plus 30%
			BigDecimal rdrtRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.3)));
			billingRate = rdrtRate;
			break;
		case RDLH:
			// Plus 160%
			BigDecimal rdlhRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1.6)));
			billingRate = rdlhRate;
			break;
		case RDSH:
			// Plus 60%
			BigDecimal rdshRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.60)));
			billingRate = rdshRate;
			break;
		case NDRT:
			// Only 10.01%
			BigDecimal ndrtRate = rateValue.multiply(BigDecimal.valueOf(0.1001));
			billingRate = ndrtRate;
			break;
		case NDSH:
			// Only 13% of the rate (10% of rate bec. of ND plus 3% bec. of SH)
			BigDecimal ndshRate = rateValue.multiply(BigDecimal.valueOf(0.13));
			billingRate = ndshRate;
			break;
		case NDLH:
			// Only 20% of the rate
			BigDecimal ndlhRate = rateValue.multiply(BigDecimal.valueOf(0.2));
			billingRate = ndlhRate;
			break;
		case HP:
			// 451 + 15 = 466 (rate + ecola)
        	// 466/8 = 58.25 per hour
        	BigDecimal hpRate = rate.value.add(ecolaRate);
			billingRate = hpRate;
			break;
		case ECOLA:
			billingRate = ecolaRate;
			break;
		default:
			System.out.println("WARNING: " + payment.paymentType
					+ " payment type not yet supported.");
		}

		if (billingRate != null) {
			paymentCalculation = billingRate.multiply(paymentHrs);
			paymentCalculation = Rounder.roundup(paymentCalculation);
		}

		return paymentCalculation;
	}

	private BigDecimal computeBasicBillingRate(final BigDecimal rateValue) {
		BigDecimal basicRate = BigDecimal.valueOf(0.00);
		BigDecimal governmentBenefits = computeGovernmentBenefitsPerHour();

		basicRate = basicRate.add(rateValue);
		basicRate = basicRate.add(governmentBenefits);

		return basicRate;
	}

	protected BigDecimal computeGovernmentBenefitsPerHour() {
		// 3thMonthPay = (BasicRatePerHour / 12months) * 8hrs
		BigDecimal thirteenthMonthPayPerDay = BigDecimal.valueOf(38.83);
		BigDecimal fiveDayIncentiveLeavePerDay = BigDecimal.valueOf(8.02);
		BigDecimal sssPerDay = BigDecimal.valueOf(34.00);
		BigDecimal philhealthPerDay = BigDecimal.valueOf(5.77);
		BigDecimal pagIbigPerDay = BigDecimal.valueOf(3.85);
		BigDecimal employeeCompensationPerDay = BigDecimal.valueOf(0.38);

		BigDecimal governmentBenefits = BigDecimal.valueOf(0.0);
		governmentBenefits = governmentBenefits.add(thirteenthMonthPayPerDay);
		governmentBenefits = governmentBenefits.add(fiveDayIncentiveLeavePerDay);
		governmentBenefits = governmentBenefits.add(sssPerDay);
		governmentBenefits = governmentBenefits.add(philhealthPerDay);
		governmentBenefits = governmentBenefits.add(pagIbigPerDay);
		governmentBenefits = governmentBenefits.add(employeeCompensationPerDay);

		// Compute per hour
		governmentBenefits = governmentBenefits.divide(BigDecimal.valueOf(8));

		return governmentBenefits;
	}

}
